<script setup lang="ts">
import { IWaterFallProps, ICardItem, ICardPos } from "./type.ts";
import { computed, onMounted, reactive, ref } from "vue";

const props = defineProps<IWaterFallProps>();

const containerRef = ref<HTMLDivElement | null>(null); // 绑定 template 上的 container，需要容器宽度
const state = reactive({
  isFinish: false, // 判断是否已经没有数据，后续不再发送请求
  page: 1,
  cardWidth: 0, // // 容器内卡片宽度
  cardList: [] as ICardItem[], // 卡片数据源
  cardPos: [] as ICardPos[], // 卡片摆放位置信息
  columnHeight: new Array(props.column).fill(0) as number[], // 存储每列的高度，进行初始化操作
});

const init = () => {
  if (containerRef.value) {
    const containerWidth = containerRef.value.clientWidth;
    state.cardWidth =
      (containerWidth - props.gap * (props.column - 1)) / props.column;
    getCardList(state.page, props.pageSize);
  }
};
const handleResize = (e) => {
  console.log("浏览器改变", window.innerWidth, window.innerHeight);
  if (containerRef.value) {
    const containerWidth = containerRef.value.clientWidth;
    state.cardWidth =
      (containerWidth - props.gap * (props.column - 1)) / props.column;
  }
  state.cardPos = [];
  computedCardPos(state.cardList);
};
onMounted(() => {
  init();
  window.addEventListener("resize", handleResize);
});

const getCardList = async (
  page: number = state.page,
  pageSize: number = state.pageSize
) => {
  if (state.isFinish) return;
  const list = await props.request(page, pageSize);
  state.page++;
  if (!list.length) {
    state.isFinish = true;
    return;
  }
  state.cardList = [...state.cardList, ...list];
  computedCardPos(list); // key：根据请求的数据计算卡片位置
};
const minColumn = computed(() => {
  let minIndex = -1,
    minHeight = Infinity;

  state.columnHeight.forEach((item, index) => {
    if (item < minHeight) {
      minHeight = item;
      minIndex = index;
    }
  });

  return {
    minIndex,
    minHeight,
  };
});
const maxHeight = computed(() => {
  return Math.max(...state.columnHeight);
});

const computedCardPos = (list: ICardItem[]) => {
  console.log(list);
  list.forEach((item, index) => {
    const cardHeight = Math.floor((item.height * state.cardWidth) / item.width);
    if (index < props.column && state.cardList.length <= props.pageSize) {
      state.cardPos.push({
        width: state.cardWidth,
        height: cardHeight,
        x:
          index % props.column !== 0
            ? index * (state.cardWidth + props.gap)
            : 0,
        y: 0,
      });
      state.columnHeight[index] = cardHeight + props.gap;
    } else {
      const { minIndex, minHeight } = minColumn.value;
      state.cardPos.push({
        width: state.cardWidth,
        height: cardHeight,
        x:
          minIndex % props.column !== 0
            ? minIndex * (state.cardWidth + props.gap)
            : 0,
        y: minHeight,
      });
      state.columnHeight[minIndex] += cardHeight + props.gap;
    }
  });
};
// const handleScroll = () => {
//   const { scrollTop, clientHeight, scrollHeight } = containerRef.value!;
//   const bottom = scrollHeight - clientHeight - scrollTop;
//   if (bottom <= props.bottom) {
//     !state.loading && getCardList(state.page, props.pageSize);
//   }
// };

defineExpose({ getCardList });
</script>

<template>
  <div class="fs-waterfall">
    <div class="fs-waterfall-container" ref="containerRef">
      <div class="fs-waterfall-list" :style="{ height: maxHeight + 'px' }">
        <div
          class="fs-waterfall-item"
          v-for="(item, index) in state.cardList"
          :key="item.id"
          :style="{
            width: `${state.cardPos[index].width}px`,
            height: `${state.cardPos[index].height}px`,
            transform: `translate3d(${state.cardPos[index].x}px, ${state.cardPos[index].y}px, 0)`,
            // background:'red'
          }"
        >
          <slot name="item" :item="item" :index="index"></slot>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
.fs-waterfall {
  &-container {
    width: 100%;
    // height: 100%;
    /* overflow-y: scroll; 
    overflow-x: hidden; */
  }

  &-list {
    width: 100%;
    // height: 100%;
    position: relative;
  }

  &-item {
    position: absolute;
    left: 0;
    top: 0;
    box-sizing: border-box;
  }
}
</style>
